package com.njchy.statistics.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * Spring Security配置类
 * 功能：
 * 1. 当swagger.enable=true时，直接访问Swagger页面（无需登录）
 * 2. 当swagger.enable=false时，访问Swagger路径直接返回404
 * 3. 所有接口均无需登录（如需限制其他接口，可调整anyRequest()配置）
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // 从配置文件读取Swagger启用状态（默认true）
    @Value("${swagger.enable}")
    private boolean swaggerEnabled;

    // 定义所有Swagger相关路径（包含子路径和变体）
    private static final List<String> SWAGGER_PATHS = Arrays.asList(
            "/doc.html",                  // Knife4j文档页
            "/webjars/**",                // 静态资源（CSS/JS）
            "/swagger-resources/**",      // Swagger资源定义
            "/v2/api-docs/**",            // v2 API文档（支持子路径）
            "/v3/api-docs/**",            // v3 API文档（支持子路径）
            "/swagger-ui/**",             // Swagger UI页面
            "/swagger-ui.html",           // Swagger UI首页
            "/favicon.ico"                // 图标
    );


    /**
     * 配置安全规则和过滤器
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 添加Swagger过滤器（优先级最高，在所有认证逻辑前执行）
        http.addFilterBefore(swaggerFilter(), UsernamePasswordAuthenticationFilter.class);

        http
                .csrf().disable()  // 禁用CSRF（适合API场景）
                .authorizeRequests()
                // 放行所有Swagger路径（无需登录）
                .antMatchers(
                        "/doc.html",
                        "/webjars/**",
                        "/swagger-resources/**",
                        "/v2/api-docs/**",
                        "/v3/api-docs/**",
                        "/swagger-ui/**",
                        "/swagger-ui.html",
                        "/favicon.ico"
                ).permitAll()
                // 其他所有接口均无需登录（如需限制可改为.anyRequest().authenticated()）
                .anyRequest().permitAll()
                .and()
                .formLogin().permitAll()  // 登录页放行（当前场景下基本用不到）
                .and()
                .logout().permitAll();    // 登出功能放行
    }

    /**
     * 自定义Swagger过滤器：拦截Swagger路径，禁用时返回404
     */
    @Bean
    public OncePerRequestFilter swaggerFilter() {
        return new OncePerRequestFilter() {
            // 用于精确匹配带通配符的路径（如/**）
            private final PathMatcher pathMatcher = new AntPathMatcher();

            @Override
            protected void doFilterInternal(
                    HttpServletRequest request,
                    HttpServletResponse response,
                    FilterChain filterChain
            ) throws ServletException, IOException {

                // 获取当前请求路径
                String requestUri = request.getRequestURI();

                // 判断当前请求是否为Swagger相关路径（支持通配符匹配）
                boolean isSwaggerPath = SWAGGER_PATHS.stream()
                        .anyMatch(path -> pathMatcher.match(path, requestUri));

                // 如果Swagger禁用且是Swagger路径，直接返回404
                if (!swaggerEnabled && isSwaggerPath) {
                    response.sendError(HttpServletResponse.SC_NOT_FOUND, "页面不存在");
                    return;
                }

                // 其他情况继续执行过滤链
                filterChain.doFilter(request, response);
            }
        };
    }

    /**
     * 密码加密器（Spring Security必须配置）
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}